package com.dmatek.uwb.local.algorithm;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.dmatek.uwb.packet.bean.AssistLocation;
import com.dmatek.uwb.packet.bean.BindNode;
import com.dmatek.uwb.packet.bean.ClosestSub;
import com.dmatek.uwb.packet.bean.CrossPoint;
import com.dmatek.uwb.packet.bean.CrossPoint.SectionSituation;
import com.dmatek.uwb.packet.bean.ENodeBDistance;
import com.dmatek.uwb.packet.bean.IterateDataFormat;
import com.dmatek.uwb.packet.bean.LocalFilter;
import com.dmatek.uwb.packet.bean.RoundLocation;
import com.dmatek.uwb.packet.bean.TagInfor;
import com.dmatek.uwb.packet.bean.Weight;
import com.dmatek.uwb.util.tool.GeometryToolkit;
import com.dmatek.uwb.util.tool.StringUtil;
import com.dmatek.uwb.xml.dom.bean.BaseNode;
import com.dmatek.uwb.xml.dom.bean.BasePath;
import com.dmatek.uwb.xml.dom.bean.BranchNode;
import com.dmatek.uwb.xml.dom.bean.BranchPath;
import com.dmatek.uwb.xml.dom.bean.Config;
import com.dmatek.uwb.xml.dom.bean.Divider;
import com.dmatek.uwb.xml.dom.bean.MainNode;
import com.dmatek.uwb.xml.dom.bean.MainPath;
import com.dmatek.uwb.xml.dom.bean.Point;
import com.dmatek.uwb.xml.dom.bean.Region;
import com.dmatek.uwb.xml.dom.bean.Side;

public abstract class BaseSingleLocalAlgorithm implements ILocalAlgorithm<TagInfor, AssistLocation> {
	private boolean debug = true;
	private Config config;
	private Map<String, Divider> dividersMap = null;
	private Map<String, Region> regionsMap = null;
	private Map<String, BaseNode> nodesMap = null;
	private Map<String, BasePath> pathsMap = null;
	private IWeightingTool weightTool;
	public BaseSingleLocalAlgorithm(Config config, Map<String, BasePath> pathsMap, Map<String, BaseNode> nodesMap,
			Map<String, Region> regionsMap, Map<String, Divider> dividersMap) throws Exception {
		super();
		// 配置类
		this.config = config;
		// 路径讯息Map类
		this.pathsMap = pathsMap;
		// 基站讯息Map类
		this.nodesMap = nodesMap;
		// 区域讯息Map类
		this.regionsMap = regionsMap;
		// 分割线Map类
		this.dividersMap = dividersMap;
		// 权重工具
		weightTool = new WeightTool();
	}
	/***
	 * 对上报的卡片的所有基站距离讯息进行分组
	 * @param tagInfor : 卡片讯息
	 * @param matchBranchs : 距离小于极限距离的基站
	 * @param disMatchBranchs : 距离大于极限距离的基站
	 * @param matchMains : 匹配主基站
	 */
	protected final void dividerENodeBDistances(TagInfor tagInfor, 
		List<ENodeBDistance> matchBranchs, List<ENodeBDistance> disMatchBranchs, 
		List<ENodeBDistance> matchMains) {
		// 遍历所有上报上来的卡片讯息，将他们分为三组
		for(ENodeBDistance eNodeBDistance:tagInfor.geteNodeBDistances().values()) {
			BaseNode node = nodesMap.get(eNodeBDistance.getId());
			if(null != node) {
				if (node instanceof BranchNode) {
					BranchNode branchNode = (BranchNode) node;
					if(eNodeBDistance.getDistance() <= branchNode.getMaxDistance()) {
						matchBranchs.add(eNodeBDistance);
					} else {
						disMatchBranchs.add(eNodeBDistance);
					}
				} else if(node instanceof MainNode) {
					matchMains.add(eNodeBDistance);
				}
			}
		}
	}
	/***
	 * 获取所有权值对应的id
	 * @param matchBranchs
	 * @return
	 */
    private final List<String> obtainWeightIds(List<ENodeBDistance> matchBranchs) {
        List<String> weightIds = new ArrayList<String>();
        for (ENodeBDistance refPos:matchBranchs) {
            if (getNodesMap().containsKey(refPos.getId())) {
            	weightIds.add(refPos.getId());
            }
        }
        return weightIds;
    }
    /***
     * 获取绑定的分割线
     * @param node1
     * @param node2
     * @return
     */
    private final List<Divider> obtainBindDivider(BaseNode node1, BaseNode node2) {
    	List<Divider> dividers = new ArrayList<Divider>();
    	// 遍历所有的分割线
    	for (Divider divider : getDividersMap().values()) {
    		// 遍历分割线绑定的基站
			for (BindNode bindNode : divider.getBindNodes()) {
				String id = bindNode.getId();
				String bindId = bindNode.getBindId();
				if ((node1.getId().equals(id) && node2.getId().equals(bindId))
				 || (node2.getId().equals(id) && node1.getId().equals(bindId))) {
	                 dividers.add(divider);
	            }
			}
		}
		return dividers;
    }
    /***
     * 获取分割线穿过的所有区域
     * @param divider
     * @return
     */
    private final List<Region> obtainAccrossRegions(Divider divider) {
        List<Region> regions = new ArrayList<Region>();
        for(Region region:regionsMap.values()) {
            if(GeometryToolkit.isLineAcrossRegion(region, new Side(divider.getStart(), divider.getEnd()))) {
                regions.add(region);
            }
        }
        return regions;
    }
    /***
     * 是否绑定穿过的区域
     * @param nid
     * @param divider
     * @return
     */
    private final boolean isBindAccrossRegion(String nid, Divider divider) {
        List<Region> regions = obtainAccrossRegions(divider);
        for(Region region:regions) {
            if (!StringUtil.isEmpty(region.getnId()) && region.getnId().equals(nid)) {
                return true;
            }
        }
        return false;
    }
    /***
     * 对上报的距离的基站按id叠加权重
     * @param divider
     * @param weightNode
     * @param matchBranchs
     */
    private final void creaseWeight(Divider divider, BaseNode weightNode, List<ENodeBDistance> matchBranchs) { // 叠加权重
        for (ENodeBDistance refPosDis:matchBranchs) {
            BaseNode node = nodesMap.get(refPosDis.getId());
            if (null != node) { // 判断是否和 weightNode 在同一侧, 当然自身也会检测到
                if (GeometryToolkit.checkSide(new Point(weightNode.getX(), weightNode.getY()), new Point(node.getX(), node.getY()), divider)) {
                    weightTool.increase(node.getId());
                } else { 
                    if (isBindAccrossRegion(node.getId(), divider)) {
                        // 虽然和当前权值基站不在同一侧，但是由于它绑定的区域被分割线分割了，它的权重也是需要 + 1才行
                        weightTool.increase(node.getId());
                    }
                }
            }
        }
    }
    /***
     * 获取匹配到的基站在房间的 位置
	 * @param matchBranchs: 
	 * @param matchMains: 
	 * @param dismatchBranchs
     * @throws Exception 
	 */
	protected Point obtainMatchBranchLocal(List<ENodeBDistance> matchBranchs, List<ENodeBDistance> matchMains, List<ENodeBDistance> dismatchBranchs,
			AssistLocation assistLocal) throws Exception {
		ENodeBDistance optimalRefPos = null;
		if(matchBranchs.size() > 1) {// 说明匹配房间的基站有两个及以上
			// 权重工具初始化
			weightTool.init(obtainWeightIds(matchBranchs));
			// 遍历所有达到最近距离的基站讯息，并且要防止重复遍历
			for (int i = 0, size = matchBranchs.size() - 1; i < size; i++) {
				for(int j = i + 1, len = matchBranchs.size(); j < len; j++) {
					// 需要进行比较的基站
					ENodeBDistance compareENodeBDistance = matchBranchs.get(i);
					// 需要被比较的基站
					ENodeBDistance beComparedENodeBDistance = matchBranchs.get(j);
					BaseNode compareENode = nodesMap.get(compareENodeBDistance.getId());
					BaseNode beComparedENode = nodesMap.get(beComparedENodeBDistance.getId());
					if(null != compareENode && null != beComparedENode) {
						// 获取这两个基站的公共分割线
						List<Divider> commonDividers = obtainBindDivider(compareENode, beComparedENode);
						// 遍历两个基站所有公共的分割线
						for (Divider commonDivider : commonDividers) {
							if(null != commonDivider) {
								if(isDebug()) { // 是否添加调试讯息
									assistLocal.addAssistRefers(compareENodeBDistance, beComparedENodeBDistance);
									assistLocal.getAssistDividers().add(commonDivider);
									assistLocal.getDes().append("房间基站【ID: " + compareENodeBDistance.getId() + 
											", Distance: " + compareENodeBDistance.getDistance() + "】和房间基站【ID: " + 
											beComparedENodeBDistance.getId() + ", Distance: " + 
											beComparedENodeBDistance.getDistance() + "】公用分割线【ID: " + 
											commonDivider.getId() + "】进行比较\r\n");
								}
								// 获取这两个基站的最优解
								CrossPoint crossPoint =  GeometryToolkit.calculateCircleOptimalPoints(
										new Point(compareENode.getX(), compareENode.getY()), 
										new Point(beComparedENode.getX(), beComparedENode.getY()), 
										compareENodeBDistance.getDistance(), 
										beComparedENodeBDistance.getDistance());
								int val = GeometryToolkit.checkSide(crossPoint.getPoints(), compareENode, beComparedENode, commonDivider);
								if(val == 1) {// 在基站1一侧包括基站1的所有基站的权重都 +1
									creaseWeight(commonDivider, compareENode, matchBranchs);
								} else if(val == 0) {
									creaseWeight(commonDivider, beComparedENode, matchBranchs);
								} else {
									// 说明与两个基站都不在同一边，查看是否有切割这连个基站绑定的区域
                                    if (isBindAccrossRegion(compareENode.getId(), commonDivider)) {
                                        // 虽然和当前权值基站不在同一侧，但是由于它绑定的区域被分割线分割了，它的权重也是需要 + 1才行
                                        weightTool.increase(compareENode.getId());
                                    } else if (isBindAccrossRegion(beComparedENode.getId(), commonDivider)) {
                                        weightTool.increase(beComparedENode.getId());
                                    }
                                    continue;
								}
							}
						}
					}
				}
			}
			 // 两两比较完以后再去判断谁的权重最大
            Weight maxWeight = weightTool.obtainMaxWeight();
            String maxId = "";
            if(null != maxWeight) {
                maxId = maxWeight.getId();
                if(isDebug()) {
                	assistLocal.getDes().append("所有权重讯息: \r\n");
                	for (Weight weight : weightTool.list()) {
                		assistLocal.getDes().append("id: " + weight.getId() + 
                				", weight: " + weight.getVal() + "\r\n");
    				}	
                }
            }
            if (!StringUtil.isEmpty(maxId)) {
                for(ENodeBDistance refPos:matchBranchs) {
                    if (maxId.equals(refPos.getId())) {
                    	optimalRefPos = refPos;
                        break;
                    }
                }
            }
		} else if(matchBranchs.size() == 1) {
			optimalRefPos = matchBranchs.get(0);
		} 
		if(null != optimalRefPos) {
			return calculateRoomWidthAisle(optimalRefPos, matchBranchs, matchMains, dismatchBranchs, assistLocal);
		}
		return new Point(-1, -1);
	}
	/***
	 * 获取主路径位置
	 * @param matchMains
	 * @param dismatchBranchs
	 * @param assistLocation
	 * @return
	 * @throws Exception
	 */
	protected Point obtainMainPosition(List<ENodeBDistance> matchMains, List<ENodeBDistance> dismatchBranchs, 
			AssistLocation assistLocation) throws Exception{
		if (matchMains.size() == 0 && dismatchBranchs.size() >= 2) { // 没有检测到任何主基站, 但检测到2个即以上的非主基站
            return obtainDismatchMainPosition(dismatchBranchs, assistLocation);
        } else if (matchMains.size() == 1 && dismatchBranchs.size() >= 1) { // 只检测到一个主基站,但检测到1个以上的非主基站
            return obtainMainWithDismatchPosition(matchMains.get(0), dismatchBranchs, assistLocation);
        } else if (matchMains.size() >= 2) { // 检测到至少两个主基站
            return obtainMainPathPosition(matchMains, dismatchBranchs, assistLocation);
        }
		return null;
	}
	/***
	 * 获取当检测到2个以上走廊基站时，卡片在走廊的位置情况
	 * @param mainReferPoses
	 * @param dismatchBranchs
	 * @param assistLocal
	 * @return
	 */
    private final Point obtainMainPathPosition(List<ENodeBDistance> mainReferPoses, List<ENodeBDistance> dismatchBranchs,
    		AssistLocation assistLocal)
    {
        if (dismatchBranchs.size() <= 0)
        { // 没有从基站
        	ENodeBDistance rfpos1 = mainReferPoses.get(0);
        	ENodeBDistance rfpos2 = mainReferPoses.get(1);
            BaseNode bn1 = nodesMap.get(rfpos1.getId());
            BaseNode bn2 = nodesMap.get(rfpos2.getId());
            if (null != bn1 && null != bn2) {
                ClosestSub closestSub = findClosestMainSub(bn1, bn2, rfpos1, rfpos2);
                if(isDebug()) {
                	assistLocal.addAssistRefers(rfpos1, rfpos2);
                }
                assistLocal.setAssistPath(closestSub.getOptimalPath());
                return closestSub.getOptimalSubPoint();
            }
        }
        else {
            if (null != dismatchBranchs && dismatchBranchs.size() >= 1) {
                // 判断两个基站是否在一条主路径上
                if (mainReferPoses.get(0).getId().equals(mainReferPoses.get(1).getId())) {
                    // 说明连个基站在一条主路径上
                	GeometryToolkit.bubbleSort_ClosestDistance(dismatchBranchs);
                	if(isDebug()) {
                		assistLocal.addAssistRefers(mainReferPoses.get(0));
                		assistLocal.addAssistRefers(mainReferPoses.get(1));
                		assistLocal.addAssistRefers(dismatchBranchs.toArray(new ENodeBDistance[0]));
                	}
                	ClosestSub closestSub = calculatePlace(dismatchBranchs, mainReferPoses.get(0), mainReferPoses.get(1));
                	if(null != closestSub) {
                        assistLocal.setAssistPath(closestSub.getOptimalPath());
                		return closestSub.getOptimalSubPoint();
                	}
                } else { // 说明并不在一条主路径上，优先选择距离近的那一条主路径
                    List<ENodeBDistance> allReferpose = new ArrayList<ENodeBDistance>(10);
                    allReferpose.addAll(mainReferPoses);
                    allReferpose.addAll(dismatchBranchs);
                    GeometryToolkit.bubbleSort_ClosestDistance(allReferpose);
                    if(isDebug()) {
                    	assistLocal.addAssistRefers(allReferpose.toArray(new ENodeBDistance[0]));
                    }
                    ClosestSub closestSub = calculatePlace(allReferpose);
                    if(null != closestSub) {
                        assistLocal.setAssistPath(closestSub.getOptimalPath());
                    	return closestSub.getOptimalSubPoint();
                    }
                }
            }
        }
		return new Point(-1, -1);
    }
	/***
	 * 检测到一个走廊基站, 但检测到1个以上的非走廊基站时，卡片在走廊的位置情况
	 * @param mainReferPos
	 * @param dismatchBranchs
	 * @param assistLocal
	 * @return
	 */
    private final Point obtainMainWithDismatchPosition(ENodeBDistance mainReferPos, List<ENodeBDistance> dismatchBranchs, 
			AssistLocation assistLocal) {
        if (dismatchBranchs.size() == 1) {
        	ENodeBDistance rfpos1 = mainReferPos;
        	ENodeBDistance rfpos2 = dismatchBranchs.get(0);
            BaseNode bn1 = nodesMap.get(rfpos1.getId());
            BaseNode bn2 = nodesMap.get(rfpos2.getId());
            if (null != bn1 && null != bn2)
            {
                ClosestSub closestSub = findClosestMainSub(bn1, bn2, rfpos1, rfpos2);
                if (null != closestSub)
                {
                	if(isDebug()) {
                		assistLocal.addAssistRefers(rfpos1, rfpos2);
                	}
                	assistLocal.setAssistPath(closestSub.getOptimalPath());
                	return closestSub.getOptimalSubPoint();
                }
            }
        } else { // 三个以上的基站
        	GeometryToolkit.bubbleSort_ClosestDistance(dismatchBranchs);
            if (null != dismatchBranchs && dismatchBranchs.size() >= 2)
            {
            	if(isDebug()) {
            		assistLocal.addAssistRefers(mainReferPos);
            		assistLocal.addAssistRefers(dismatchBranchs.toArray(new ENodeBDistance[0]));
            	}
            	ClosestSub closestSub = calculatePlace(dismatchBranchs, mainReferPos);
            	if(null != closestSub) {
                	assistLocal.setAssistPath(closestSub.getOptimalPath());
            		return closestSub.getOptimalSubPoint();
            	}
            }
        }
        return new Point(-1, -1);
    }
	/***
	 * 检测房间基站两个以上，卡片在走廊的位置情况
	 * @param dismatchBranchs
	 * @param assistLocal
	 * @return
	 */
    private final Point obtainDismatchMainPosition(List<ENodeBDistance> dismatchBranchs, AssistLocation assistLocal) {
        if (dismatchBranchs.size() == 2) {
        	ENodeBDistance rfpos1 = dismatchBranchs.get(0);
        	ENodeBDistance rfpos2 = dismatchBranchs.get(1);
            BaseNode bn1 = nodesMap.get(rfpos1.getId());
            BaseNode bn2 = nodesMap.get(rfpos2.getId());
            if (null != bn1 && null != bn2) {
                ClosestSub closestSub = findClosestMainSub(bn1, bn2, rfpos1, rfpos2);
                if(isDebug()) {
            		assistLocal.addAssistRefers(rfpos1, rfpos2);
            		if(null != closestSub) {
            			assistLocal.addAssistRefers(rfpos1, rfpos2);
            		}
            	}
                if(null != closestSub) {
                	assistLocal.setAssistPath(closestSub.getOptimalPath());
                	return closestSub.getOptimalSubPoint();
                }
            }
        } else { // 3个及以上，我们需要先对它进行排序，
            // 对列表中的基站按距离小到大进行排序
        	GeometryToolkit.bubbleSort_ClosestDistance(dismatchBranchs);
            if (null != dismatchBranchs && dismatchBranchs.size() >= 3) {
            	// 添加选择的参考点
            	if(isDebug()) {
            		assistLocal.addAssistRefers(dismatchBranchs.toArray(new ENodeBDistance[0]));
            	}
            	ClosestSub closestSub = calculatePlace(dismatchBranchs);
            	if(null != closestSub) {
            		closestSub.setOptimalPath(closestSub.getOptimalPath());
            		return closestSub.getOptimalSubPoint();
            	}
            }
        }
        return new Point(-1, -1);
    }
	/***
	 * 运行三点/两点计算最优坐标
	 * @param rounds
	 * @return
	 */
	private final Point calculateLocation(List<RoundLocation> rounds) {
        // 当前的园是按照从小到大排序的
        RoundLocation rounda = null, 
        			  roundb = null;
        rounda = rounds.get(0);
        roundb = rounds.get(1);
        if (rounds.size() >= 3) {
            double maxAngle = 0f;
            List<LocalFilter> localFilters = new ArrayList<LocalFilter>();
            for (int i = 2, size = rounds.size(); i < size; i++) { // 计算出一个坐标了
            	List<IterateDataFormat> iterates = new ArrayList<IterateDataFormat>();
            	iterates.add(new IterateDataFormat(rounda.getCenter().getX(), rounda.getCenter().getY(), rounda.getR()));
            	iterates.add(new IterateDataFormat(roundb.getCenter().getX(), roundb.getCenter().getY(), roundb.getR()));
            	iterates.add(new IterateDataFormat(rounds.get(i).getCenter().getX(), rounds.get(i).getCenter().getY(), rounds.get(i).getR()));
            	maxAngle = GeometryToolkit.obtainMaxAngle(rounda.getCenter(), roundb.getCenter(), rounds.get(i).getCenter());
            	@SuppressWarnings("deprecation")
				IterateDataFormat iterateData = LocalAlgorithm.INSTANCE.dimenIndoorPosAlgorithm(iterates);
            	if(null != iterateData) {
            		Point local = new Point(iterateData.getX(), iterateData.getY());
                	localFilters.add(new LocalFilter(local, maxAngle, rounda.getId(), roundb.getId(), rounds.get(i).getId(), 
                    		rounda.geteNodeBDistance(), roundb.geteNodeBDistance(), 
                    		rounds.get(i).geteNodeBDistance()));
                }
            }
            return filterLocals(localFilters, new Divider(rounda.getCenter(), roundb.getCenter()));
        } else if (rounds.size() >= 2) {
        	List<IterateDataFormat> iterates = new ArrayList<IterateDataFormat>();
        	iterates.add(new IterateDataFormat(rounds.get(0).getCenter().getX(), rounds.get(0).getCenter().getY(), rounds.get(0).getR()));
        	iterates.add(new IterateDataFormat(rounds.get(1).getCenter().getX(), rounds.get(1).getCenter().getY(), rounds.get(1).getR()));
        	@SuppressWarnings("deprecation")
			IterateDataFormat iterateData = LocalAlgorithm.INSTANCE.dimenIndoorPosAlgorithm(iterates);
        	if(null != iterateData) {
        		return new Point(iterateData.getX(), iterateData.getY());
        	}
        }
        return new Point(-1, -1);
    }
	/***
	 * 将所有上报的基站距离转成RoundLocation对象
	 * @param refPoses
	 * @param fixRefPoses
	 * @return
	 */
	private final List<RoundLocation> obtainRoundLocations(List<ENodeBDistance> refPoses, ENodeBDistance... fixRefPoses) {
		List<RoundLocation> roundLocations = new ArrayList<RoundLocation>();
        // 将固定的先添加到列表中
        for(ENodeBDistance fixRefPos:fixRefPoses) {
            BaseNode node = nodesMap.get(fixRefPos.getId());
            if (null != node) {
                roundLocations.add(new RoundLocation(fixRefPos.getId(), 
                		new Point(node.getX(), node.getY()), 
                		(double)(fixRefPos.getDistance()), 
                		fixRefPos));
            }
        }
        for(ENodeBDistance refPos:refPoses)
        {
            BaseNode node = nodesMap.get(refPos.getId());
            if (null != node) {
                roundLocations.add(new RoundLocation(refPos.getId(), 
                		new Point(node.getX(), node.getY()), 
                		(double)(refPos.getDistance()), 
                		refPos));
            }
        }
        return roundLocations;
    }
	/***
	 * 根据选择的基站距离对象计算卡片位置
	 * @param refPoses
	 * @param fixRefPoses
	 * @return
	 */
	private final ClosestSub calculatePlace(List<ENodeBDistance> refPoses, 
			ENodeBDistance... fixRefPoses) {
		List<RoundLocation> roundLocals = obtainRoundLocations(refPoses, fixRefPoses);
        Point place = calculateLocation(roundLocals);
        if (place.getX() > 0 || place.getY() > 0) {
            ClosestSub closestSub = findClosestMainSub(place);
            if (null != closestSub) {
                return closestSub;
            }
        }
        return null;
    }
	/***
	 * 查找当前坐标最近的投影点
	 * @param place
	 * @return
	 */
	private final ClosestSub findClosestMainSub(Point place) {
        ClosestSub closeSub = new ClosestSub(Double.MAX_VALUE, new Point(-1, -1), null);
        for(BasePath path:pathsMap.values()) {
        	if (path instanceof MainPath) {
				Point subPoint = GeometryToolkit.UVProject(path, place);
				double distance = GeometryToolkit.pixelPitch(subPoint, place);
				if (distance < closeSub.getMinDistance()) {
					closeSub.setMinDistance(distance);
					closeSub.setOptimalSubPoint(subPoint);
					closeSub.setOptimalPath(path);  
	            }
			}
        }
        return closeSub;
    }
	/***
	 * 根据上报的基站距离计算坐标最近的投影点
	 * @param bn1
	 * @param bn2
	 * @param rfpos1
	 * @param rfpos2
	 * @return
	 */
	private final ClosestSub findClosestMainSub(BaseNode bn1, BaseNode bn2, 
			ENodeBDistance rfpos1, ENodeBDistance rfpos2) {
		CrossPoint crossPoint = GeometryToolkit.calculateCircleOptimalPoints(new Point(bn1.getX(), bn1.getY()), 
        		new Point(bn2.getX(), bn2.getY()), (float)(rfpos1.getDistance()), 
                (float)(rfpos2.getDistance()));
        ClosestSub closetSub = null;
        // 找所有主路径上投影距离最短位置
        if (crossPoint.getSectionSituation() == SectionSituation.TT1) {
            closetSub = findClosestMainSub(crossPoint.getPoints()[0]);
        } else {
            ClosestSub cs1 = findClosestMainSub(crossPoint.getPoints()[0]);
            ClosestSub cs2 = findClosestMainSub(crossPoint.getPoints()[1]);
            // 查看是否位于同一条路径
            if (cs1.getOptimalPath().getId().equals(cs2.getOptimalPath().getId())) { // 返回距离短的投影点
                closetSub = (cs1.getMinDistance() < cs2.getMinDistance() ? cs1: cs2);
            } else { // 不能确认
            	
            }
        }
        return closetSub;
    }
	/***
	 * 根据基站距离情况计算卡片在房间或走廊上
	 * @param matchBranchPos
	 * @param matchBranchs
	 * @param matchMains
	 * @param disMatchBranchs
	 * @param assistLocal
	 * @return
	 * @throws Exception
	 */
	private final Point calculateRoomWidthAisle(ENodeBDistance matchBranchPos,
			List<ENodeBDistance> matchBranchs, List<ENodeBDistance> matchMains, 
			List<ENodeBDistance> disMatchBranchs, 
			AssistLocation assistLocal) throws Exception {
        BaseNode matchNode = nodesMap.get(matchBranchPos.getId());
        if (null != matchNode) {
           if (matchNode instanceof BranchNode) {
            BasePath path = pathsMap.get(((BranchNode)matchNode).getBpId());
            if (null != path) {
                for (ENodeBDistance mr:matchMains) {
                    BaseNode mn = nodesMap.get(mr.getId());
                    if (null != mn) {
                        List<Divider> dividers = obtainBindDivider(mn, matchNode);
                        for(Divider divider:dividers) {
                            if (null != divider)
                            {
                                /* 与当前走廊上报的基站存在公共边, 
                                 * 需要判断这两个相交的位置再哪一个地方
                                 * 在走廊我们就说当前处在走廊区域，
                                 * 反之处在房间区域
                                 */
                            	if(isDebug()) {
                            		assistLocal.getAssistDividers().add(divider);
                            		assistLocal.addAssistRefers(matchBranchPos, mr);
                            		assistLocal.getDes().append("房间基站【ID: " + matchBranchPos.getId() + 
                            				", Distance: " + matchBranchPos.getDistance() + "】和走廊基站【ID: " + 
                            				mr.getId() + ", Distance: " + mr.getDistance() + "】公用分割线【ID: " + 
                            				divider.getId() + "】进行比较\r\n");
                            	}
                            	CrossPoint crossPoint = GeometryToolkit.calculateCircleOptimalPoints(new Point(mn.getX(), mn.getY()), 
                                			   new Point(matchNode.getX(), matchNode.getY()),
                                               (float)(mr.getDistance()), 
                                               (float)(matchBranchPos.getDistance()));
                                int val = GeometryToolkit.isRoomWithAisle(crossPoint.getPoints(), matchNode, mn, divider);
                                if (val == 1)
                                { // 处在房间
                                	assistLocal.setAssistPath(path);
                                	return GeometryToolkit.calculateRoomPlace((BranchPath)path, (BranchNode)matchNode, matchBranchPos);
                                } else if (val == 0) { // 处在走廊 mn： 是主路径基站必须选择，
                                    /*
                                     * 如果在走廊我们就可以根据走廊的判断规则
                                     */
                                    List<ENodeBDistance> allBranchs = new ArrayList<ENodeBDistance>();
                                    allBranchs.addAll(matchBranchs);
                                    allBranchs.addAll(disMatchBranchs);
                                    if(isDebug()) {
                                		assistLocal.getAssistRefers().clear();
                                	}
                                    return obtainMainPosition(matchMains, allBranchs, assistLocal);
                                } else { // 不能确定位置

                                }
                                return null;
                            }
                        }
                    }
                }
                if(isDebug()) {
                	assistLocal.addAssistRefers(matchBranchPos);
                }
                assistLocal.setAssistPath(path);
                // 不存在任何公共分割线，则表示当前处在房间中
                return GeometryToolkit.calculateRoomPlace((BranchPath)path, (BranchNode)matchNode, matchBranchPos);
              }
           }
        }
		return null;
    }
	/***
	 * 屏蔽三个基站定位时可能接近直线上，导致定位不准问题
	 * @param localFilters
	 * @param divider
	 * @return
	 */
	private final Point filterLocals(List<LocalFilter> localFilters, Divider divider) {
        if (localFilters.size() >= 2) {  // 两个需要判断是否在同一侧
            if (GeometryToolkit.checkSide(localFilters.get(1).getLocal(), 
            		localFilters.get(0).getLocal(), divider)) {
                return localFilters.get(0).getLocal();
            } else {
                if (localFilters.get(0).getAngle() > localFilters.get(1).getAngle()) {
                    return localFilters.get(1).getLocal();
                } else {
                    return localFilters.get(0).getLocal();
                }
            }
        } else if (localFilters.size() == 1) {
            return localFilters.get(0).getLocal();
        }
        return new Point(-1, -1);
    }
	public Config getConfig() {
		return config;
	}
	public void setConfig(Config config) {
		this.config = config;
	}
	public Map<String, Divider> getDividersMap() {
		return dividersMap;
	}
	public void setDividersMap(Map<String, Divider> dividersMap) {
		this.dividersMap = dividersMap;
	}
	public Map<String, Region> getRegionsMap() {
		return regionsMap;
	}
	public void setRegionsMap(Map<String, Region> regionsMap) {
		this.regionsMap = regionsMap;
	}
	public Map<String, BaseNode> getNodesMap() {
		return nodesMap;
	}
	public void setNodesMap(Map<String, BaseNode> nodesMap) {
		this.nodesMap = nodesMap;
	}
	public boolean isDebug() {
		return debug;
	}
	public void setDebug(boolean debug) {
		this.debug = debug;
	}
	public Map<String, BasePath> getPathsMap() {
		return pathsMap;
	}
	public void setPathsMap(Map<String, BasePath> pathsMap) {
		this.pathsMap = pathsMap;
	}
}
